<?php

namespace App\Api\Controllers;

use App\Api\Requests\AddressRequest;
use App\Api\Requests\OrderRequest;
use App\Api\Resources\ProductResource;
use App\Models\OrderModel;
use App\Models\PatientAddressModel;
use App\Models\PatientModel;
use App\Models\ProductModel;
use GuzzleHttp\Client;
use Illuminate\Database\Console\Migrations\ResetCommand;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Str;
use EasyWeChat\Factory;
use PHPUnit\Util\Exception;


class KingdeeController
{

    protected $username = '17220202021';
    protected $password = 'Jdy202101';
    protected $clientId = '205022';
    protected $clientSecret = '1b16d77089b1e60b3f7c907aa3cc612e';
    protected $groupName = 'ns-v7g15';
    protected $accountId = '1626231450425742965';
    protected $token = '';
    protected $kingdeeTokenKey = '__KingdeeAccessToken__';
    const API_DOMAIN = 'http://api.kingdee.com';
    protected $sandbox = true;
    protected $payConfig = [];

    public function __construct()
    {
        $this->config = [
            // 必要配置
            'app_id'             => 'wx6e3ec7142f33d118',
            'secret'             => 'd1eb7ec1e964c8312cfb0d0141d23a66',
            'response_type'      => 'array',
        ];

        $this->payConfig = [
            // 必要配置
            'app_id'             => 'wx6e3ec7142f33d118',
            'mch_id'             => '1622632141',
            'key'                => 'b1b83e116225a77b74ef1646a317dafD',   // API v2 密钥 (注意: 是v2密钥 是v2密钥 是v2密钥)
            // 如需使用敏感接口（如退款、发送红包等）需要配置 API 证书路径(登录商户平台下载 API 证书)
            'cert_path'          => 'path/to/your/cert.pem', // XXX: 绝对路径！！！！
            'key_path'           => 'path/to/your/key',      // XXX: 绝对路径！！！！
            'notify_url'         => '默认的订单回调地址',     // 你也可以在下单时单独设置来想覆盖它
            'sandbox'            => $this->sandbox,
        ];
    }
    //
    // private function makeAccessToken()
    // {
    //     if (Redis::get($this->kingdeeTokenKey)) {
    //         $this->token = Redis::get($this->kingdeeTokenKey);
    //     } else {
    //         $client = new Client(['headers' => ['Content-Type' => 'application/json']]);
    //         $res = $client->request('GET', self::API_DOMAIN . '/auth/user/access_token', [
    //             'query' => [
    //                 'username' => $this->username,
    //                 'password' => $this->password,
    //                 'client_id' => $this->clientId,
    //                 'client_secret' => $this->clientSecret,
    //             ]
    //         ]);
    //         $body = $res->getBody();
    //         $contents = json_decode($body->getContents(), true);
    //         if (isset($contents['data']['access_token'])) {
    //             $this->token = $contents['data']['access_token'];
    //             Redis::set($this->kingdeeTokenKey, $this->token);
    //         } else {
    //             echo $contents['message'];die;
    //         }
    //     }
    // }
    //
    // private function sendQuery($url, $query, $method='POST')
    // {
    //     $client = new Client([
    //         'headers' => [
    //             'Content-Type' => 'Application/Json;charset=utf-8',
    //             'groupName' => $this->groupName,
    //             'accountId' => $this->accountId
    //         ]
    //     ]);
    //     $url = self::API_DOMAIN . $url . '?access_token=' . $this->token;
    //     $res = $client->request($method, $url , [
    //         'json' => $query
    //     ]);
    //     $body = $res->getBody();
    //     $contents = json_decode($body->getContents(), true);
    //     return $contents;
    // }

    private function success($data=[], $code=200)
    {
        return response()->json([
            'code' => $code,
            'success' => true,
            'data' => $data,
        ]);
    }

    private function error($message, $code=400)
    {
        return response()->json([
            'code' => $code,
            'success' => false,
            'message' => $message
        ]);
    }

    public function getProductList(Request $request)
    {

        // $query['parent'] = ['1469536463686222848', '1469536539175308288', '1469569427593773056'];
        // $res = $this->sendQuery('/jdy/basedata/material_list', $query);
        // if ($res['success'] == true) {
        //     return $this->success($res['data']);
        // } else {
        //     return $this->error($res['errorMsg']);
        // }
        try {
            $products = ProductModel::where('product_status', 1)->where('product_stock', '>', 0)->orderBy('product_sort', 'desc')->get();
            return $this->success(ProductResource::collection($products));
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function getProductDetail(Request $request)
    {
        // try {
        //     if ($request->input('id') === null) throw new \Exception('参数错误');
        //
        //     $res = $this->sendQuery('/jdy/basedata/material_detail', ['id' => $request->input('id')]);
        //     if ($res['success'] == true) {
        //         return $this->success($res['data']);
        //     } else {
        //         throw new \Exception($res['errorMsg']);
        //     }
        //
        // } catch (\Exception $e) {
        //     return $this->error($e->getMessage());
        // }
        try {
            if ($request->input('data_id') === null) throw new \Exception('参数错误');
            $product = ProductModel::has('service')->find($request->input('data_id'));
            if ($product === null) throw new \Exception('数据异常');
            return $this->success(new ProductResource($product));
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    // private function syncPatientToKingdee($patient)
    // {
    //     $params = [
    //         'name' => $patient->patients_name . ' - ' . $patient->patients_mobile,
    //         'ignorewarn' => true
    //     ];
    //     $res = $this->sendQuery('/jdy/basedata/customer_save', $params);
    //     Log::channel('kingdee')->info('syncPatientToKingdee 患者信息同步到金蝶结果===', $res);
    //     if ($res['success'] == true) {
    //         $kingdeeCustomerId = $res['data']['successPkIds'][0];
    //         // 同步到patient
    //         $sync = PatientModel::where('data_id', $patient->data_id)->update(['kingdee_customer_id' => $kingdeeCustomerId]);
    //         if (!$sync) Log::channel('kingdee')->error("syncPatientToKingdee数据更新本地数据库失败", $sync);
    //         return $sync;
    //     } else {
    //         Log::channel('kingdee')->error("syncPatientToKingdee调用API失败", $res);
    //         return false;
    //     }
    // }

    public function createOrder(OrderRequest $request)
    {
        try {

            $patientId = $request->input('patient_id');
            $addressId = $request->input('address_id');
            $products = $request->input('products');

            // 开启事物
            DB::beginTransaction();
            $patient = PatientModel::find($patientId);
            if ($patient == null) throw new \Exception('数据异常');

            // $kingdeeCustomerId = $patient->kingdee_customer_id;
            // if (empty($kingdeeCustomerId)) {
            //     $syncStatus = $this->syncPatientToKingdee($patient);
            //     if (!$syncStatus) throw new \Exception('数据同步失败');
            // }

            // 配送到家校验收货地址
            if ($request->input('delivery_type') == 1) {
                $patientAddress = PatientAddressModel::find($addressId);
                if ($patientAddress == null) throw new \Exception('收货地址据异常');
            }

            if (!is_array($products)) throw new \Exception('商品信息异常');

            // TODO 存储订单信息
            $orderData = [
                'data_id' => md5(Str::uuid()),
                'order_info_userid' => $patientId,
                'order_info_title' => implode('、', Arr::pluck($products, 'name')),
                'order_info_no' => date('ymdHis').str_pad(random_int(0, 999999), 6, '0'),
                'order_info_sum' => array_sum(Arr::pluck($products, 'num')),
                'order_info_payment' => (array_sum(Arr::pluck($products, 'price')) * 100),
                'order_info_paystatus' => 0,    // 未支付
                'order_info_orderstatus' => 0,  // 待支付
                'order_info_type' => 0,     // 商城订单
                'order_info_pay_type' => 2, // 微信支付
                'remark' => $request->input('remark'),
                'order_info_delivery_type' => $request->input('delivery_type'),
                'order_info_buy_type' => $request->input('buy_type', 0)
            ];
            $order = OrderModel::create($orderData);
            if (!$order) throw new \Exception('订单创建失败');

            // 创建订单对应的商品信息
            $productData = [];
            foreach ($products as $item) {
                $productInfo = ProductModel::find($item['id']);
                if ($productInfo === null) continue;
                $productData[] = [
                    'product_id' => $item['id'],
                    'product_name' => $productInfo['product_name'],
                    'product_price' => $productInfo['product_price'],
                    'product_category' => $productInfo['product_category'],
                    'product_discount_price' => $productInfo['product_discount_price'],
                    'product_service_id' => $productInfo['product_service_id'],
                    'product_num' => $item['num']
                ];
            }
            if (empty($productData)) throw new \Exception('商品信息异常');

            $product = $order->products()->createMany($productData);
            if (!$product) throw new \Exception('商品信息保存失败');

            // 创建订单对应的收货地址信息
            if ($request->input('delivery_type') == 1) {
                $address = $order->address()->create([
                    'contact_person' => $patientAddress->contact_person,
                    'contact_phone' => $patientAddress->contact_phone,
                    'contact_address' => $patientAddress->contact_full_address,
                ]);
                if (!$address) throw new \Exception('收货信息保存失败');
            }

            DB::commit();
            return $this->success(['order_id' => $order->data_id]);

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->error($e->getMessage());
        }
    }

    public function jssdk()
    {
        try {
            $app = Factory::officialAccount($this->config);
            return $this->success($app->jssdk->buildConfig(['chooseWXPay'], true, false, false));

        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function wechatPay(Request $request)
    {
        try {

            if ($request->input('order_id') === null || $request->input('patient_id') === null) throw new Exception('参数错误');

            $app = Factory::payment($this->payConfig);

            // TODO 获取订单信息
            $order = OrderModel::find($request->input('order_id'));
            if ($order === null) throw new \Exception('异常订单');

            // TODO 获取患者信息
            $patient = PatientModel::find($request->input('patient_id'));
            if ($patient === null) throw new \Exception('患者信息异常');

            $result = $app->order->unify([
                'body' => $order->order_info_title,
                'out_trade_no' => $order->order_info_no,
                'total_fee' => $this->sandbox ? 101 : $order->order_info_payment,
                'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
                'openid' => $patient->wx_oa_openid
            ]);

            if ($result['return_code'] == 'FAIL') throw new \Exception($result['return_msg']);

            $data = $app->jssdk->bridgeConfig($result['prepay_id'], false);
            if ($result['return_code'] == 'SUCCESS') {
                return $this->success($data);
            } else {
                throw new \Exception($result['return_msg']);
            }

        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function getOrderStatus(Request $request)
    {
        $this->success();
    }

    private function createQrcode($orderId)
    {
        $app = Factory::officialAccount($this->config);
        $data = json_encode(['userId' => null, 'qrCodeType' => 4, 'others' => $orderId]);
        $result = $app->qrcode->forever($data);
        return $result;
    }

    public function payCallback()
    {

        $payApp = Factory::payment($this->payConfig);
        $response = $payApp->handlePaidNotify(function ($message, $fail) {
            try {
                // 根据返回的订单号查询订单数据
                $orderInfo = OrderModel::with(['products'])->where('order_info_no', $message['out_trade_no'])->first();
                if ($orderInfo == null) throw new \Exception('订单不存在');

                // 已支付
                if ($orderInfo->order_info_paystatus == 1) return true;
                // 已支付、已完成
                if (in_array($orderInfo->order_info_orderstatus, [3, 4])) return true;

                if($message['result_code'] === 'SUCCESS') {
                    $orderInfo->order_info_paystatus = 1;
                    $orderInfo->order_info_orderstatus = 3;
                    $orderInfo->transaction_id = $message['transaction_id'];
                    // 2 为试纸，不需要生成二维码
                    if ($orderInfo->products != null && $orderInfo->products[0]['product_category'] != 2) {
                        $qrcode = $this->createQrcode($orderInfo->data_id);
                        $orderInfo->order_info_qrcode = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket='.urlencode($qrcode['ticket']);
                        $orderInfo->order_info_qrcode_result = $qrcode['url'];
                    }
                    $save = $orderInfo->save();
                    if (!$save) throw new \Exception('数据处理失败');
                }

                return true;

            } catch (\Exception $e) {
                Log::channel('wechat_pay')->error($e->getMessage());
                return $fail($e->getMessage());
            }
        });
        return $response;
    }

    public function getAddress(Request $request)
    {
        try {

            if($request->input('patient_id') === null) throw new \Exception('参数错误');

            $data = PatientAddressModel::where('patient_id', $request->input('patient_id'))
                ->where('is_del', 0)
                ->orderBy('create_time', 'desc')
                ->get();

            return $this->success($data);
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function editPatientAddress(AddressRequest $request)
    {
        try {

            $status = PatientAddressModel::updateOrCreate(['data_id' => $request->input('data_id')], [
                'patient_id' => $request->input('patient_id'),
                'contact_person' => $request->input('contact_person'),
                'contact_phone' => $request->input('contact_phone'),
                'contact_province_id' => $request->input('contact_province_id'),
                'contact_province_name' => $request->input('contact_province_name'),
                'contact_city_id' => $request->input('contact_city_id'),
                'contact_city_name' => $request->input('contact_city_name'),
                'contact_district_id' => $request->input('contact_district_id'),
                'contact_district_name' => $request->input('contact_district_name'),
                'contact_address' => $request->input('contact_address'),
                'is_default' => $request->input('is_default', 0),
            ]);

            return $status ? $this->success() : $this->error('操作失败');
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function deletePatientAddress(Request $request)
    {
        try {

            if($request->input('data_id') === null) throw new \Exception('参数错误');

            $data = PatientAddressModel::find($request->input('data_id'));
            $data->is_del = 1;
            $status = $data->save();

            return $status ? $this->success() : $this->error('操作失败');
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }
}
